package com.audaque.springboot.foshanupload.redis.component;

import com.audaque.springboot.foshanupload.core.exception.RetryMaxException;
import com.audaque.springboot.foshanupload.core.exception.RetryingException;
import com.audaque.springboot.foshanupload.redis.model.dto.AsyncResultDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @author zgb
 * @desc ...
 * @date 2022-02-28 20:24:54
 */
@Slf4j
@Component
public class AsyncRetryer {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;




    @Recover
    public void recover(RetryingException e) throws RetryMaxException {
        String message = e.getMessage();
        String r = "重试次数已达上限:" + message;
        log.warn(r);
        //不要使用Exception，否则自定义异常信息丢失，要使用自定义 RetryMaxException extends RuntimeException
        throw new RetryMaxException(r);
    }

    //retry不能有返回值,retry代替while或递归，调用者不要catch RetryException否则会把Exception抓住，导致Exception丢失
    @Retryable(value = RetryingException.class, maxAttempts = Integer.MAX_VALUE, backoff = @Backoff(value =  5* 1000, maxDelay = 1*60 * 1000, multiplier = 1.1))
    public void retry(String paramCountKey, String productCountKey, String consumeCountKey,String reportListSizeKey,String overListSizeKey) throws RetryingException {

        String paramCount = stringRedisTemplate.opsForValue().get(paramCountKey);
        String productCount = stringRedisTemplate.opsForValue().get(productCountKey);
        String consumeCount = stringRedisTemplate.opsForValue().get(consumeCountKey);
        String reportListSizeStr = stringRedisTemplate.opsForValue().get(reportListSizeKey);
        String overListSizeStr = stringRedisTemplate.opsForValue().get(overListSizeKey);
        int reportListSize = Integer.parseInt(reportListSizeStr);
        int overListSize = Integer.parseInt(overListSizeStr);

        if(reportListSize>0||overListSize>0){
            int paramCounti = 0;
            if (StringUtils.isNotBlank(paramCount)) {
                paramCounti = Integer.parseInt(paramCount);
            }
            if (paramCounti == 0) {
                String msg="队列任务未开始入队，继续轮询";
                log.warn(msg);
                throw new RetryingException(msg);
            }

        }




        AsyncResultDto asyncResultDto = new AsyncResultDto();
        asyncResultDto.setParamInteger(Integer.parseInt(paramCount));
        asyncResultDto.setProductInteger(Integer.parseInt(productCount));
        asyncResultDto.setConsumeInteger(Integer.parseInt(consumeCount));
        log.warn("正在轮询是否所有任务已结束");
        log.warn("上报实时计数：listForeachEventAsyncResultDto:"+ asyncResultDto);

        if (Objects.equals(Integer.parseInt(paramCount), Integer.parseInt(productCount))
                &&
                Objects.equals(Integer.parseInt(consumeCount), Integer.parseInt(productCount))
        ) {
            log.warn("所有任务已结束");
            return;

        } else {
            String msg="所有任务未结束，继续轮询";
            log.warn(msg);
            throw new RetryingException(msg);

        }

    }




}
